package org.zeuzgroup.tradeskill.runesofmagic;

import java.awt.Color;
import java.awt.Point;
import java.awt.Robot;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;

import org.slf4j.Logger;
import org.zeuzgroup.console.Utils;
import org.zeuzgroup.general.Bar;
import org.zeuzgroup.general.Pointer;

public class Gatherer {

	static final Logger log = org.slf4j.LoggerFactory
			.getLogger(Gatherer.class);

	private Bar healthBar;
	private Bar manaBar;
	private Pointer pointer;
	private Robot robot;

	public Gatherer(Robot robot) {
		this.robot = robot;
	}

	public void gather(int timesToLoop) {
		for (int i = 0; i < timesToLoop; i++) {
			moveToItem();
			scanAndGather();
			robot.delay(5000);
			if(detectIfUnderAttack()){
				quitGame();
			}
		}
		quitGame();
	}

	private void moveToItem() {
		robot.delay(1500);
		ImageDetection im = new ImageDetection(robot);
		Point playerPoint = new Point(46, 42);
		Point lastPoint = null;
		int numberOfFailures = 0;
		double lastDistance = 0;
		for (int i = 0; i < 50; i++) {
			Point itemLocation = im.detect();
			double distance = playerPoint.distance(itemLocation);
			if (distance == 0) {
				break;
			} else {
				if (numberOfFailures > 5) {
					// okay we tried to move but point shifts all the time,
					// finding new area to search.
					numberOfFailures = 0;
					// moving down for five seconds.
					Utils.keyHitAndRelease(robot, KeyEvent.VK_DOWN, 5000);
				}
				int duration = (int) (75 * distance);
				int previousDuration = (int) (75 * lastDistance);
				// focus
				log.info("Distance :" + distance);
				// Utils.mouseClickAndRelease(robot, InputEvent.BUTTON1_MASK);
				log.info("Item Location x dif:"
						+ (itemLocation.x - playerPoint.x));
				log.info("Item Location y dif:"
						+ (itemLocation.y - playerPoint.y));
				if (lastDistance < distance && distance > 5 && lastPoint != null) {
					log.info("somethings wrong moving wrong direction");
					move(lastPoint.x - playerPoint.x, KeyEvent.VK_LEFT,
							KeyEvent.VK_RIGHT, robot, previousDuration);
					move(lastPoint.y - itemLocation.y, KeyEvent.VK_DOWN,
							KeyEvent.VK_UP, robot, previousDuration);

					numberOfFailures++;
				}
				if (lastDistance < 5 && lastPoint != null) {
					log.info("Close enough for scan gatherhing");
					return;

				} else {
					move(itemLocation.x - playerPoint.x, KeyEvent.VK_LEFT,
							KeyEvent.VK_RIGHT, robot, duration);
					move(playerPoint.y - itemLocation.y, KeyEvent.VK_DOWN,
							KeyEvent.VK_UP, robot, duration);
					lastPoint = itemLocation;
					lastDistance = distance;

				}

			}

			robot.delay(500);
			// when location of harvest item are 46,42 then you are right on top
			// and can begin gathering

		}

		
	}
	private static void move(double point, int keyMinus, int keyPlus,
			Robot robot, int duration) {
		if (point > 1) {
			Utils.keyHitAndRelease(robot, keyPlus, duration);
		}
		if (point < -1) {
			Utils.keyHitAndRelease(robot, keyMinus, duration);
		}
	}

	private boolean detectIfUnderAttack() {
		// TODO Auto-generated method stub
		return false;
	}

	private void quitGame() {
		Utils.keyHitAndRelease(robot, KeyEvent.VK_ESCAPE);
		robot.mouseMove(400, 345);
		Utils.mouseClickAndRelease(robot, InputEvent.BUTTON1_MASK);
		robot.mouseMove(350, 135);
		Utils.mouseClickAndRelease(robot, InputEvent.BUTTON1_MASK);
	}
	private void scanAndGather() {
		boolean foundGatheringSign=findGatheringSignAndMoveMouse();
		if(foundGatheringSign)
		{
		activateGathering();
		}
		
	}

	private boolean findGatheringSignAndMoveMouse() {
		// 210 200 +400 +250
		int numberofSteps=10;
		int xSteps=400/numberofSteps;
		int ySteps=250/numberofSteps;
		for(int x=1;x<numberofSteps;x++)
		{
			for(int y=1;y<numberofSteps;y++)
			{
				int realY=x*xSteps+200;
				int realX=y*ySteps+250;
				robot.mouseMove(realX, realY);
				robot.delay(500);
				if(scanForGatheringSignAtMouseLocation()){
					return true;
				}
			}
			
		}
		return false;
	}
		
	private boolean scanForGatheringSignAtMouseLocation() {

		Point currentPos = java.awt.MouseInfo.getPointerInfo().getLocation();
		int yFrom = 0, yTo = 0, xFrom = 0, xTo = 0;
		yFrom = currentPos.y + pointer.getOffSetPoint().y - 20;
		yTo = currentPos.y + pointer.getOffSetPoint().y + 20;
		xFrom = currentPos.x + pointer.getOffSetPoint().x - 10;
		xTo = currentPos.x + pointer.getOffSetPoint().x + 10;
		for (int y = yFrom; y < yTo; y++) {
			for (int x = xFrom; x < xTo; x++) {
				// robot.mouseMove(x, y);
				Color screenColor = robot.getPixelColor(x, y);
				for (Color c : pointer.getColors()) {
					log.info("See if gathering active");
					if (Utils.isWithinOffSet(c, screenColor, 20)) {
						log.info("found gathering sign!");
						return true;
					}

				}

			}

		}
		return false;

	}

	private void activateGathering() {
		log.info("Grabbing Something");
		robot.mousePress(InputEvent.BUTTON1_MASK);
		robot.delay(500);
		robot.mouseRelease(InputEvent.BUTTON1_MASK);
		robot.delay(5000);

	}

	public void setup() {
		log.info("Setup");
		healthBar = new Bar("health bar", 20, new Color(204, 0, 0));
		manaBar = new Bar("mana bar", 20, new Color(0, 0, 177));
		// not really the point as that are hidden
		// pointer here 417,271 thing to detect here 447,279
		// offset 30,8
		pointer = new Pointer(new Point(30, 8), new Color(234, 234, 0));
		scanleftSideForBars();

	}

	private void scanleftSideForBars() {
		log.info("scaning");
		// from x 70 to 180
		// from y 0 to 30
		for (int y = 27; y < 53; y++) {
			for (int x = 70; x < 180; x++) {
				Color color = robot.getPixelColor(x, y);
				checkAndWalk(manaBar, x, y, color);
				checkAndWalk(healthBar, x, y, color);
				if (manaBar.isFromAndToAssigned()
						&& healthBar.isFromAndToAssigned()) {
					log.debug("done scanning bar");

				}
			}
		}

	}

	private void checkAndWalk(Bar bar, int x, int y, Color color) {
		// logger.info("CheckAndWalk");
		if (!bar.isFromAndToAssigned()
				&& Utils.isWithinOffSet(bar.getColor(), color, bar.getOffSet())) {
			log.info("Got a match");
			walkTheLineAndAssign(bar, new Point(x, y));
		}
	}

	private void walkTheLineAndAssign(Bar bar, Point point) {
		log.info("walkTheLineAndAssign");
		for (int i = point.x; i < 1000; i++) {

			Color color = robot.getPixelColor(i, point.y);

			if (!Utils.isWithinOffSet(bar.getColor(), color, bar.getOffSet())) {
				bar.setFrom(point);
				bar.setTo(new Point(i, point.y));
				log.info("found " + bar.getName() + " ranges from "
						+ bar.getFrom().toString() + " to "
						+ bar.getTo().toString());
				break;

			}

		}

	}

}
